package com.stenio.fancat.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.green.extension.uploader.ClientUploader;
import com.aliyuncs.green.model.v20180509.*;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.stenio.fancat.util.DateUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.*;

/**
 * @author zhangqiu
 * @date 2018/12/6
 * @desc
 **/
@Service
@SuppressWarnings("all")
public class OssService {
    @Value("${oss.endpoint}")
    private String endpoint;
    @Value("${oss.access-key-id}")
    private String accessKeyId;
    @Value("${oss.access-key-secret}")
    private String accessKeySecret;
    @Value("${oss.bucket}")
    private String bucketName;
    public List<String> suggestions;

    /**
     * 上传bean
     * @return
     */
    @Bean
    public OSSClient createOSSClient() {
        OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        return client;
    }

    /**
     * 检测bean
     * @return
     */
    @Bean
    public IAcsClient createIAcsClient() {
        IClientProfile profile = DefaultProfile
                .getProfile("cn-beijing", accessKeyId, accessKeySecret);
        try {
            DefaultProfile
                    .addEndpoint("cn-beijing", "cn-beijing", "Green", "green.cn-beijing.aliyuncs.com");
        } catch (ClientException e) {
            e.printStackTrace();
        }
        IAcsClient client = new DefaultAcsClient(profile);
        return client;
    }

    /**
     * 上传
     * @param objectName
     * @param bytes
     * @return
     */
    public PutObjectResult putObject(String objectName, byte[] bytes){
        return createOSSClient().putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
    }

    public PutObjectResult putObjectSecond(String objectName, byte[] bytes){
        return createOSSClient().putObject("piggybank-photos", objectName, new ByteArrayInputStream(bytes));
    }

    /**
     * 通过二进制检测图片
     * @param bytes
     * @return
     */
    public List<String> ckeckObject(byte[] bytes) {
        IAcsClient client = createIAcsClient();
        suggestions = new ArrayList<String>();

        ImageSyncScanRequest imageSyncScanRequest = new ImageSyncScanRequest();
        // 指定api返回格式
        imageSyncScanRequest.setAcceptFormat(FormatType.JSON);
        // 指定请求方法
        imageSyncScanRequest.setMethod(MethodType.POST);
        imageSyncScanRequest.setEncoding("utf-8");
        //支持http和https
        imageSyncScanRequest.setProtocol(ProtocolType.HTTPS);


        JSONObject httpBody = new JSONObject();
        //监黄监政
        httpBody.put("scenes", Arrays.asList("porn","terrorism"));


        //如果您要检测的文件存于本地服务器上，可以通过下述代码片生成url，
        //再将返回的url作为图片地址传递到服务端进行检测

        ClientUploader uploader = ClientUploader.getImageClientUploader(client);
        byte[] imageBytes = bytes;
        String url = uploader.uploadBytes(imageBytes);


         //设置待检测图片， 一张图片一个task，
         //多张图片同时检测时，处理的时间由最后一个处理完的图片决定。
         //通常情况下批量检测的平均rt比单张检测的要长, 一次批量提交的图片数越多，rt被拉长的概率越高
         //这里以单张图片检测作为示例, 如果是批量图片检测，请自行构建多个task

        JSONObject task = new JSONObject();
        task.put("dataId", UUID.randomUUID().toString());

        //设置图片链接为上传后的url
        task.put("url", url);
        task.put("time", new Date());
        httpBody.put("tasks", Arrays.asList(task));

        imageSyncScanRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(httpBody.toJSONString()),
                "UTF-8", FormatType.JSON);


         //请设置超时时间, 服务端全链路处理超时时间为10秒，请做相应设置
         //如果您设置的ReadTimeout 小于服务端处理的时间，程序中会获得一个read timeout 异常

        imageSyncScanRequest.setConnectTimeout(3000);
        imageSyncScanRequest.setReadTimeout(10000);
        HttpResponse httpResponse = null;
        try {
            httpResponse = client.doAction(imageSyncScanRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //服务端接收到请求，并完成处理返回的结果
        if (httpResponse != null && httpResponse.isSuccess()) {
            JSONObject scrResponse = JSON.parseObject(org.apache.commons.codec.binary.StringUtils.newStringUtf8(httpResponse.getHttpContent()));
            int requestCode = scrResponse.getIntValue("code");
            //每一张图片的检测结果
            JSONArray taskResults = scrResponse.getJSONArray("data");
            if (200 == requestCode) {
                for (Object taskResult : taskResults) {
                    //单张图片的处理结果
                    int taskCode = ((JSONObject) taskResult).getIntValue("code");
                    //图片要检测的场景的处理结果, 如果是多个场景，则会有每个场景的结果
                    JSONArray sceneResults = ((JSONObject) taskResult).getJSONArray("results");
                    if (200 == taskCode) {
                        for (Object sceneResult : sceneResults) {
                            String suggestion = ((JSONObject) sceneResult).getString("suggestion");
                            suggestions.add(suggestion);
                        }
                    }
                }
            }
        }
        return suggestions;
    }

    /**
     * 通过url检测图片
     * @param url
     * @return
     */
    public List<String> ckeckUrl(String url) {
        suggestions = new ArrayList<String>();
        IAcsClient client = createIAcsClient();
        ImageSyncScanRequest imageSyncScanRequest = new ImageSyncScanRequest();
        // 指定api返回格式
        imageSyncScanRequest.setAcceptFormat(FormatType.JSON);
        // 指定请求方法
        imageSyncScanRequest.setMethod(MethodType.POST);
        imageSyncScanRequest.setEncoding("utf-8");
        //支持http和https
        imageSyncScanRequest.setProtocol(ProtocolType.HTTP);


        JSONObject httpBody = new JSONObject();
        //监黄监政
        httpBody.put("scenes", Arrays.asList("porn","terrorism"));

        JSONObject task = new JSONObject();
        task.put("dataId", UUID.randomUUID().toString());


        //设置图片链接
        task.put("url", url);
        task.put("time", new Date());
        httpBody.put("tasks", Arrays.asList(task));

        imageSyncScanRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(httpBody.toJSONString()),
                "UTF-8", FormatType.JSON);

        /**
         * 请设置超时时间, 服务端全链路处理超时时间为10秒，请做相应设置
         * 如果您设置的ReadTimeout 小于服务端处理的时间，程序中会获得一个read timeout 异常
         */
        imageSyncScanRequest.setConnectTimeout(3000);
        imageSyncScanRequest.setReadTimeout(10000);
        HttpResponse httpResponse = null;
        try {
            httpResponse = client.doAction(imageSyncScanRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //服务端接收到请求，并完成处理返回的结果
        if (httpResponse != null && httpResponse.isSuccess()) {
            JSONObject scrResponse = JSON.parseObject(org.apache.commons.codec.binary.StringUtils.newStringUtf8(httpResponse.getHttpContent()));
            int requestCode = scrResponse.getIntValue("code");
            //每一张图片的检测结果
            JSONArray taskResults = scrResponse.getJSONArray("data");
            if (200 == requestCode) {
                for (Object taskResult : taskResults) {
                    //单张图片的处理结果
                    int taskCode = ((JSONObject) taskResult).getIntValue("code");
                    //图片要检测的场景的处理结果, 如果是多个场景，则会有每个场景的结果
                    JSONArray sceneResults = ((JSONObject) taskResult).getJSONArray("results");
                    if (200 == taskCode) {
                        for (Object sceneResult : sceneResults) {
                            String suggestion = ((JSONObject) sceneResult).getString("suggestion");
                            suggestions.add(suggestion);
                        }
                    }
                }
            }
        }
        return suggestions;
    }


    /**
     * 通过二进制异步检测图片
     * @param bytes
     * @return
     */
    public String ckeckObjectAsync(byte[] bytes){
        String taskId = null;
        IAcsClient client = createIAcsClient();
        ImageAsyncScanRequest imageAsyncScanRequest = new ImageAsyncScanRequest();
        // 指定api返回格式
        imageAsyncScanRequest.setAcceptFormat(FormatType.JSON);
        // 指定请求方法
        imageAsyncScanRequest.setMethod(MethodType.POST);
        imageAsyncScanRequest.setEncoding("utf-8");
        //支持http和https
        imageAsyncScanRequest.setProtocol(ProtocolType.HTTP);


        JSONObject httpBody = new JSONObject();
        //监黄监政
        httpBody.put("scenes", Arrays.asList("porn","terrorism"));

        ClientUploader uploader = ClientUploader.getImageClientUploader(client);
        byte[] imageBytes = bytes;
        String url = uploader.uploadBytes(imageBytes);


        JSONObject task = new JSONObject();
        task.put("dataId", UUID.randomUUID().toString());

        //设置图片链接
        task.put("url", url);
        task.put("time", new Date());
        httpBody.put("tasks", Arrays.asList(task));

        imageAsyncScanRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(httpBody.toJSONString()),
                "UTF-8", FormatType.JSON);

        /**
         * 请设置超时时间, 服务端全链路处理超时时间为10秒，请做相应设置
         * 如果您设置的ReadTimeout 小于服务端处理的时间，程序中会获得一个read timeout 异常
         */
        imageAsyncScanRequest.setConnectTimeout(3000);
        imageAsyncScanRequest.setReadTimeout(10000);
        HttpResponse httpResponse = null;
        try {
            httpResponse = client.doAction(imageAsyncScanRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (httpResponse != null && httpResponse.isSuccess()) {
            JSONObject scrResponse = JSON.parseObject(org.apache.commons.codec.binary.StringUtils.newStringUtf8(httpResponse.getHttpContent()));
            int requestCode = scrResponse.getIntValue("code");
            //每一张图片的检测结果
            JSONArray taskResults = scrResponse.getJSONArray("data");
            if (200 == requestCode) {
                for (Object taskResult : taskResults) {
                    //单张图片的处理结果
                    int taskCode = ((JSONObject) taskResult).getIntValue("code");
                    //图片要检测的场景的处理结果, 如果是多个场景，则会有每个场景的结果
                    JSONArray sceneResults = ((JSONObject) taskResult).getJSONArray("results");
                    if (200 == taskCode) {
                        //保存taskId用于轮询结果
                        taskId = ((JSONObject)taskResult).getString("taskId");
                    }
                }
            }
        }
        return taskId;
    }

    /**
     * 二进制异步检测回调图片
     * @param taskId
     * @return
     * @throws UnsupportedEncodingException
     */
    public List<String> ckeckObjectAsyncCallBack(String taskId) throws UnsupportedEncodingException {
        suggestions = new ArrayList<String>();
        IAcsClient client = createIAcsClient();
        ImageAsyncScanResultsRequest imageAsyncScanResultsRequest = new ImageAsyncScanResultsRequest();
        // 指定api返回格式
        imageAsyncScanResultsRequest.setAcceptFormat(FormatType.JSON);
        // 指定请求方法
        imageAsyncScanResultsRequest.setMethod(MethodType.POST);
        imageAsyncScanResultsRequest.setEncoding("utf-8");
        //支持http和https
        imageAsyncScanResultsRequest.setProtocol(ProtocolType.HTTP);


        List<String> taskIds = new ArrayList<String>();
        taskIds.add(taskId);
        try {
            imageAsyncScanResultsRequest.setHttpContent(JSON.toJSONString(taskIds).getBytes("UTF-8"), "UTF-8", FormatType.JSON);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        /**
         * 请务必设置超时时间
         */
        imageAsyncScanResultsRequest.setConnectTimeout(3000);
        imageAsyncScanResultsRequest.setReadTimeout(6000);

        HttpResponse httpResponse = null;
        try {
            httpResponse = client.doAction(imageAsyncScanResultsRequest);
        } catch (Exception e){
            e.printStackTrace();
        }
        if(httpResponse.isSuccess()){
            JSONObject scrResponse = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
            System.out.println(JSON.toJSONString(scrResponse, true));
            if (200 == scrResponse.getInteger("code")) {
                JSONArray taskResults = scrResponse.getJSONArray("data");
                for (Object taskResult : taskResults) {
                    if(200 == ((JSONObject)taskResult).getInteger("code")){
                        JSONArray sceneResults = ((JSONObject)taskResult).getJSONArray("results");
                        for (Object sceneResult : sceneResults) {
                            String scene = ((JSONObject)sceneResult).getString("scene");
                            String suggestion = ((JSONObject)sceneResult).getString("suggestion");
                            //根据scene和suggetion做相关的处理
                            //do something
                        }
                    }else{
                        System.out.println("task process fail:" + ((JSONObject)taskResult).getInteger("code"));
                    }
                }
            } else {
                System.out.println("detect not success. code:" + scrResponse.getInteger("code"));
            }
        }else{
            System.out.println("response not success. status:" + httpResponse.getStatus());
        }
        return suggestions;
    }

    /**
     * url异步检测视频
     * @return
     * @throws UnsupportedEncodingException
     * @throws ClientException
     */
    public String checkVideoAnsy() throws UnsupportedEncodingException, ClientException {
        IAcsClient client = createIAcsClient();

        VideoAsyncScanRequest videoAsyncScanRequest = new VideoAsyncScanRequest();
        videoAsyncScanRequest.setAcceptFormat(FormatType.JSON); // 指定api返回格式
        videoAsyncScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); // 指定请求方法

        List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
        Map<String, Object> task = new LinkedHashMap<String, Object>();
        task.put("dataId", UUID.randomUUID().toString());
        task.put("url", "https://piggybank.oss-cn-beijing.aliyuncs.com/321/ee35c7f1-6f6c-4d13-861b-d157eb21e308.mp4");

        tasks.add(task);
        /**
         * 设置要检测的场景, 计费是按照该处传递的场景进行
         * 视频默认1秒截取一帧，您可以自行控制截帧频率，收费按照视频的截帧数量以及每一帧的检测场景进行计费
         * 举例：1分钟的视频截帧60张，检测色情和暴恐涉政2个场景，收费按照60张暴恐+60张暴恐涉政进行计费
         * porn: porn表示色情场景检测,terrorism表示暴恐涉政场景检测
         */
        JSONObject data = new JSONObject();
        data.put("scenes", Arrays.asList("porn", "terrorism"));
        data.put("tasks", tasks);

        videoAsyncScanRequest.setHttpContent(data.toJSONString().getBytes("UTF-8"), "UTF-8", FormatType.JSON);

        /**
         * 请务必设置超时时间
         */
        videoAsyncScanRequest.setConnectTimeout(3000);
        videoAsyncScanRequest.setReadTimeout(6000);
        String taskId = "";
        try {
            HttpResponse httpResponse = client.doAction(videoAsyncScanRequest);

            if(httpResponse.isSuccess()){
                JSONObject jsonObject = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
                JSONArray taskResults = jsonObject.getJSONArray("data");
                for(Object taskResult : taskResults) {
                    taskId = ((JSONObject) taskResult).getString("taskId");
                }
                //System.out.println(JSON.toJSONString(jsonObject, true));
            }else{
                System.out.println("response not success. status:" + httpResponse.getStatus());
            }
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return taskId;
    }

    /**
     * url异步检测视频回调
     * @param taskId
     * @return
     * @throws UnsupportedEncodingException
     */
    public List<String> checkVideoCallBack(String taskId) throws UnsupportedEncodingException {
        IAcsClient client = createIAcsClient();
        VideoAsyncScanResultsRequest videoAsyncScanResultsRequest = new VideoAsyncScanResultsRequest();
        videoAsyncScanResultsRequest.setAcceptFormat(FormatType.JSON);

        List<String> taskList = new ArrayList<String>();
        // 这里添加要查询的taskId，提交任务的时候需要自行保存taskId
        taskList.add(taskId);

        videoAsyncScanResultsRequest.setHttpContent(JSON.toJSONString(taskList).getBytes("UTF-8"), "UTF-8", FormatType.JSON);

        /**
         * 请务必设置超时时间
         */
        videoAsyncScanResultsRequest.setConnectTimeout(3000);
        videoAsyncScanResultsRequest.setReadTimeout(6000);
        try {
            HttpResponse httpResponse = client.doAction(videoAsyncScanResultsRequest);
            if(httpResponse.isSuccess()) {
                JSONObject scrResponse = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
                int requestCode = scrResponse.getIntValue("code");
                //每一张图片的检测结果
                JSONArray taskResults = scrResponse.getJSONArray("data");
                if (200 == requestCode) {
                    for (Object taskResult : taskResults) {
                        //单张图片的处理结果
                        int taskCode = ((JSONObject) taskResult).getIntValue("code");
                        //图片要检测的场景的处理结果, 如果是多个场景，则会有每个场景的结果
                        JSONArray sceneResults = ((JSONObject) taskResult).getJSONArray("results");
                        if (200 == taskCode) {
                            for (Object sceneResult : sceneResults) {
                                String suggestion = ((JSONObject) sceneResult).getString("suggestion");
                                suggestions.add(suggestion);
                            }
                        }
                    }
                }
            }
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return suggestions;
    }

    /**
     *
     * @MethodName: updateFile
     * @Description: 更新文件:只更新内容，不更新文件名和文件地址。
     * 		(因为地址没变，可能存在浏览器原数据缓存，不能及时加载新数据，例如图片更新，请注意)
     * @param bytes  文件
     * @return String
     */
    public PutObjectResult updateFile(String fileName, byte[] bytes){
        if(null == fileName)
            return null;
        return putObject(fileName,bytes);
    }

    /**
     * 批量删除oss文件，每次上限1000个
     * @param keys 文件名称
     * @return 删除失败文件名称
     */
    public List<String> deleteFileList(List<String> keys) {
        OSSClient ossClient = createOSSClient();
        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys).withQuiet(true));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        // 关闭OSSClient。
        ossClient.shutdown();
        return deletedObjects;
    }

    /**
     * 截取文件名称，用于oss文件删除
     * @param str  文件名称
     * @return
     */
    public String splitName(String str) {
        String[] split = str.split("/", 4);
        return split[split.length-1];
    }


    /**
     * 生成图片新的名字       --------------------图片名字改为当前调用的时间戳------------------
     * @param sourceName
     * @return
     */
    public String getImageName(String sourceName,String babyId,String behaviorId){
        Long time = new Date().getTime();
        //拼接名字
        StringBuffer sb = new StringBuffer();
        sb.append(babyId);
        sb.append("/");
        sb.append(behaviorId);
        sb.append("/");
        sb.append(DateUtil.format(new Date(),"yyyyMMdd"));
        sb.append("/");
        sb.append(time.toString());
        sb.append(sourceName.substring(sourceName.lastIndexOf(".")));
        return sb.toString();
    }


    /**
     * 生成头像新的名字
     * @param sourceName
     * @param babyId
     * @return
     */
    public String getIconName(String sourceName,String babyId){
        StringBuffer sb = new StringBuffer();
        sb.append(babyId);
        sb.append(sourceName.substring(sourceName.lastIndexOf(".")));
        return sb.toString();
    }

}
